﻿using System;
using System.Collections.Generic;
using Transformable_Engine_v2.Engine.Global;
using Transformable_Engine_v2.Engine.Graphics;
using Transformable_Engine_v2.Engine.Rendering;
using Transformable_Engine_v2.Engine.Transformable_Math.Geometry;

namespace Transformable_Engine_v2.Engine.GameObjects.Containers.Transformable_controls
{
    public class Label : ImageContainer
    {
        private const string UnknownCharacter = "Unknown";

        private readonly Dictionary<string, string> _specialCharacters = new Dictionary<string, string>
            {
                {"0", "Num0"},
                {"1", "Num1"},
                {"2", "Num2"},
                {"3", "Num3"},
                {"4", "Num4"},
                {"5", "Num5"},
                {"6", "Num6"},
                {"7", "Num7"},
                {"8", "Num8"},
                {"9", "Num9"},
                {".", "Period"},
                {",", "Comma"},
                {"?", "InterrogationPoint"},
                {"!", "ExclamationPoint"},
                {"@", "At"},
                {"#", "Hashtag"},
                {"$", "DollarSign"},
                {"%", "PercentSign"},
                {":", "Colon"},
                {";", "Semicolon"},
                {"_", "Underscore"},
                {"<", "LesserThan"},
                {">", "GreaterThan"},
                {"=", "Equal"},
                {"/", "ForwardSlash"},
                {"\\", "BackwardsSlash"}
            }; 

        public void SetText(params string[] text)
        {
            Text = text;
        }

        public string[] Text { get; set; }

        public TE_Rectangle.Alignment TextAlign { get; set; }

        private Func<string, Sprite> GetSprite;

        public override void AddChildren(params Container[] children)
        {
            throw new Exception("This control cannot have any children");
        }

        public Label(Func<string, Sprite> getSpriteMethod, params string[] text)
        {
            Text = text;
            TextAlign = TE_Rectangle.Alignment.TopLeft;

            GetSprite = getSpriteMethod;
            Sprite = GetSprite(UnknownCharacter);
        }

        public override void Draw()
        {
            if(!Visible)
                return;
            TE_Vector2 letterSize = GetSprite(UnknownCharacter).SpriteArea.Size;
            TE_Vector2 originalPosition = new TE_Vector2(Position);
            float offsetY = 0;

            switch(TextAlign) {
                case TE_Rectangle.Alignment.TopLeft:
                case TE_Rectangle.Alignment.TopMiddle:
                case TE_Rectangle.Alignment.TopRight:
                    offsetY = 0;
                    break;
                case TE_Rectangle.Alignment.CenterLeft:
                case TE_Rectangle.Alignment.CenterMiddle:
                case TE_Rectangle.Alignment.CenterRight:
                    offsetY = -(Scale.Y*letterSize.Y*Text.Length)/2;
                    break;
                case TE_Rectangle.Alignment.BottomLeft:
                case TE_Rectangle.Alignment.BottomMiddle:
                case TE_Rectangle.Alignment.BottomRight:
                    offsetY = -(Scale.Y*letterSize.Y*Text.Length);
                    break;
            }

            foreach (var line in Text) 
            {
                if(line != null)
                    DrawLine(line, originalPosition, offsetY, letterSize);
                offsetY += letterSize.Y * Scale.Y;
            }

            Position = originalPosition;
        }

        void DrawLine(string line, TE_Vector2 originalPosition, float offsetY, TE_Vector2 letterSize)
        {
            float offsetX = 0;

            switch(TextAlign) {
                case TE_Rectangle.Alignment.TopLeft:
                case TE_Rectangle.Alignment.CenterLeft:
                case TE_Rectangle.Alignment.BottomLeft:
                    offsetX = 0;
                    break;
                case TE_Rectangle.Alignment.TopMiddle:
                case TE_Rectangle.Alignment.CenterMiddle:
                case TE_Rectangle.Alignment.BottomMiddle:
                    offsetX = -(Scale.X*letterSize.X*line.Length)/2;
                    break;
                case TE_Rectangle.Alignment.TopRight:
                case TE_Rectangle.Alignment.CenterRight:
                case TE_Rectangle.Alignment.BottomRight:
                    offsetX = -(Scale.X*letterSize.X*line.Length);
                    break;
            }

            foreach (var character in line) 
            {
                DrawLetter(character.ToString(), originalPosition.X + offsetX, originalPosition.Y + offsetY);
                offsetX += (Scale.X*letterSize.X);
            }
        }

        void DrawLetter(string letter, float positionX, float positionY)
        {
            if(letter == " ")
                return;

            if (_specialCharacters.ContainsKey(letter))
                letter = _specialCharacters[letter];

            Sprite character = GetSprite(letter) ?? GetSprite(UnknownCharacter);

            Position = new TE_Vector2(positionX, positionY);
            Sprite = character;

            if (ShaderHandler.HasShader)
                RenderTargetHandler.GetCurrentRenderTarget().Draw(_drawableObject, ShaderHandler.CurrentShader);
            else
                RenderTargetHandler.GetCurrentRenderTarget().Draw(_drawableObject);
        }
    }
}